home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / tos / g__~1 / gplibs17.zoo / xgetopt.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-02  |  8.3 KB  |  253 lines

  1. /*
  2. Getopt for GNU. 
  3. Copyright (C) 1987, 1989 Free Software Foundation, Inc.
  4.  
  5. (Modified by Douglas C. Schmidt for use with GNU G++.)
  6. This file is part of the GNU C++ Library.  This library is free
  7. software; you can redistribute it and/or modify it under the terms of
  8. the GNU Library General Public License as published by the Free
  9. Software Foundation; either version 2 of the License, or (at your
  10. option) any later version.  This library is distributed in the hope
  11. that it will be useful, but WITHOUT ANY WARRANTY; without even the
  12. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  13. PURPOSE.  See the GNU Library General Public License for more details.
  14. You should have received a copy of the GNU Library General Public
  15. License along with this library; if not, write to the Free Software
  16. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18.  
  19. #ifdef __GNUG__
  20. #pragma implementation
  21. #endif
  22. /* AIX requires the alloca decl to be the first thing in the file. */
  23. #ifdef __GNUC__
  24. #define alloca __builtin_alloca
  25. #elif defined(sparc)
  26. #include <alloca.h>
  27. #elif defined(_AIX)
  28. #pragma alloca
  29. #else
  30. char *alloca ();
  31. #endif
  32. #include <xgetopt.h>
  33.  
  34. char* GetOpt::nextchar = 0;
  35. int GetOpt::first_nonopt = 0;
  36. int GetOpt::last_nonopt = 0;
  37.  
  38. GetOpt::GetOpt (int argc, char **argv, const char *optstring)
  39.  :opterr (1), nargc (argc), nargv (argv), noptstring (optstring)
  40. {
  41.   /* Initialize the internal data when the first call is made.
  42.      Start processing options with ARGV-element 1 (since ARGV-element 0
  43.      is the program name); the sequence of previously skipped
  44.      non-option ARGV-elements is empty.  */
  45.  
  46.   first_nonopt = last_nonopt = optind = 1;
  47.   optarg = nextchar = 0;
  48.  
  49.   /* Determine how to handle the ordering of options and nonoptions.  */
  50.  
  51.   if (optstring[0] == '-')
  52.     ordering = RETURN_IN_ORDER;
  53.   else if (getenv ("_POSIX_OPTION_ORDER") != 0)
  54.     ordering = REQUIRE_ORDER;
  55.   else
  56.     ordering = PERMUTE;
  57. }
  58.  
  59. void
  60. GetOpt::exchange (char **argv)
  61. {
  62.   size_t nonopts_size
  63.     = (last_nonopt - first_nonopt) * sizeof (char *);
  64.   char **temp = (char **) alloca (nonopts_size);
  65.  
  66.   /* Interchange the two blocks of data in argv.  */
  67.  
  68.   memcpy (temp, &argv[first_nonopt], nonopts_size);
  69.   memcpy (&argv[first_nonopt], &argv[last_nonopt],
  70.          (optind - last_nonopt) * sizeof (char *));
  71.   memcpy (&argv[first_nonopt + optind - last_nonopt], temp,
  72.          nonopts_size);
  73.  
  74.   /* Update records for the slots the non-options now occupy.  */
  75.  
  76.   first_nonopt += (optind - last_nonopt);
  77.   last_nonopt = optind;
  78. }
  79.  
  80. /* Scan elements of ARGV (whose length is ARGC) for option characters
  81.    given in OPTSTRING.
  82.  
  83.    If an element of ARGV starts with '-', and is not exactly "-" or "--",
  84.    then it is an option element.  The characters of this element
  85.    (aside from the initial '-') are option characters.  If `getopt'
  86.    is called repeatedly, it returns successively each of theoption characters
  87.    from each of the option elements.
  88.  
  89.    If `getopt' finds another option character, it returns that character,
  90.    updating `optind' and `nextchar' so that the next call to `getopt' can
  91.    resume the scan with the following option character or ARGV-element.
  92.  
  93.    If there are no more option characters, `getopt' returns `EOF'.
  94.    Then `optind' is the index in ARGV of the first ARGV-element
  95.    that is not an option.  (The ARGV-elements have been permuted
  96.    so that those that are not options now come last.)
  97.  
  98.    OPTSTRING is a string containing the legitimate option characters.
  99.    A colon in OPTSTRING means that the previous character is an option
  100.    that wants an argument.  The argument is taken from the rest of the
  101.    current ARGV-element, or from the following ARGV-element,
  102.    and returned in `optarg'.
  103.  
  104.    If an option character is seen that is not listed in OPTSTRING,
  105.    return '?' after printing an error message.  If you set `opterr' to
  106.    zero, the error message is suppressed but we still return '?'.
  107.  
  108.    If a char in OPTSTRING is followed by a colon, that means it wants an arg,
  109.    so the following text in the same ARGV-element, or the text of the following
  110.    ARGV-element, is returned in `optarg.  Two colons mean an option that
  111.    wants an optional arg; if there is text in the current ARGV-element,
  112.    it is returned in `optarg'.
  113.  
  114.    If OPTSTRING starts with `-', it requests a different method of handling the
  115.    non-option ARGV-elements.  See the comments about RETURN_IN_ORDER, above.  */
  116.  
  117. int
  118. GetOpt::operator () (void)
  119. {
  120.   if (nextchar == 0 || *nextchar == 0)
  121.     {
  122.       if (ordering == PERMUTE)
  123.         {
  124.           /* If we have just processed some options following some non-options,
  125.              exchange them so that the options come first.  */
  126.  
  127.           if (first_nonopt != last_nonopt && last_nonopt != optind)
  128.             exchange (nargv);
  129.           else if (last_nonopt != optind)
  130.             first_nonopt = optind;
  131.  
  132.           /* Now skip any additional non-options
  133.              and extend the range of non-options previously skipped.  */
  134.  
  135.           while (optind < nargc
  136.                  && (nargv[optind][0] != '-'
  137.                      || nargv[optind][1] == 0))
  138.             optind++;
  139.           last_nonopt = optind;
  140.         }
  141.  
  142.       /* Special ARGV-element `--' means premature end of options.
  143.          Skip it like a null option,
  144.          then exchange with previous non-options as if it were an option,
  145.          then skip everything else like a non-option.  */
  146.  
  147.       if (optind != nargc && !strcmp (nargv[optind], "--"))
  148.         {
  149.           optind++;
  150.  
  151.           if (first_nonopt != last_nonopt && last_nonopt != optind)
  152.             exchange (nargv);
  153.           else if (first_nonopt == last_nonopt)
  154.             first_nonopt = optind;
  155.           last_nonopt = nargc;
  156.  
  157.           optind = nargc;
  158.         }
  159.  
  160.       /* If we have done all the ARGV-elements, stop the scan
  161.          and back over any non-options that we skipped and permuted.  */
  162.  
  163.       if (optind == nargc)
  164.         {
  165.           /* Set the next-arg-index to point at the non-options
  166.              that we previously skipped, so the caller will digest them.  */
  167.           if (first_nonopt != last_nonopt)
  168.             optind = first_nonopt;
  169.           return EOF;
  170.         }
  171.      
  172.       /* If we have come to a non-option and did not permute it,
  173.          either stop the scan or describe it to the caller and pass it by.  */
  174.  
  175.       if (nargv[optind][0] != '-' || nargv[optind][1] == 0)
  176.         {
  177.           if (ordering == REQUIRE_ORDER)
  178.             return EOF;
  179.           optarg = nargv[optind++];
  180.           return 0;
  181.         }
  182.  
  183.       /* We have found another option-ARGV-element.
  184.          Start decoding its characters.  */
  185.  
  186.       nextchar = nargv[optind] + 1;
  187.     }
  188.  
  189.   /* Look at and handle the next option-character.  */
  190.  
  191.   {
  192.     char c = *nextchar++;
  193.     char *temp = (char *) strchr (noptstring, c);
  194.  
  195.     /* Increment `optind' when we start to process its last character.  */
  196.     if (*nextchar == 0)
  197.       optind++;
  198.  
  199.     if (temp == 0 || c == ':')
  200.       {
  201.         if (opterr != 0)
  202.           {
  203.             if (c < 040 || c >= 0177)
  204.               fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
  205.                        nargv[0], c);
  206.             else
  207.               fprintf (stderr, "%s: unrecognized option `-%c'\n",
  208.                        nargv[0], c);
  209.           }
  210.         return '?';
  211.       }
  212.     if (temp[1] == ':')
  213.       {
  214.         if (temp[2] == ':')
  215.           {
  216.             /* This is an option that accepts an argument optionally.  */
  217.             if (*nextchar != 0)
  218.               {
  219.                 optarg = nextchar;
  220.                 optind++;
  221.               }
  222.             else
  223.               optarg = 0;
  224.             nextchar = 0;
  225.           }
  226.         else
  227.           {
  228.             /* This is an option that requires an argument.  */
  229.             if (*nextchar != 0)
  230.               {
  231.                 optarg = nextchar;
  232.                 /* If we end this ARGV-element by taking the rest as an arg,
  233.                    we must advance to the next element now.  */
  234.                 optind++;
  235.               }
  236.             else if (optind == nargc)
  237.               {
  238.                 if (opterr != 0)
  239.                   fprintf (stderr, "%s: no argument for `-%c' option\n",
  240.                            nargv[0], c);
  241.                 c = '?';
  242.               }
  243.             else
  244.               /* We already incremented `optind' once;
  245.                  increment it again when taking next ARGV-elt as argument.  */
  246.               optarg = nargv[optind++];
  247.             nextchar = 0;
  248.           }
  249.       }
  250.     return c;
  251.   }
  252. }
  253.